package se.perp.c4.net;

import java.util.HashMap;
import java.util.Map;
import se.perp.c4.model.Actor.EActor;
import se.perp.c4.model.Actor.Side;
import se.perp.c4.model.Card.ECard;
import se.perp.c4.model.Game.ShelobRule;
import se.perp.c4.model.Move;
import se.perp.c4.model.Territory.ETerritory;

class Codec {

    public static int encodeActor(EActor ea) {
        return ea.ordinal();
    }

    public static EActor decodeActor(int iea) {
        return EActor.values()[iea];
    }

    public static int encodeTerritory(ETerritory et) {
        return et.ordinal();
    }

    public static ETerritory decodeTerritory(int iet) {
        return ETerritory.values()[iet];
    }

    public static int encodeMove(Move m) {
        int atk = m.attacker.ordinal();
        int def = (m.defender.ordinal() << 8);
        int from = (m.from.ordinal()) << 16;
        int to = (m.to.ordinal()) << 24;

        int ret = atk | def | from | to;
        return ret;
    }

    public static Move decodeMove(int im) {
        int atkOrd = im & 0xFF;
        int defOrd = (im & 0xFF00) >> 8;
        int fromOrd = (im & 0xFF0000) >> 16;
        int toOrd = (im & 0xFF000000) >> 24;

        return new Move(
                decodeActor(atkOrd),
                decodeActor(defOrd),
                decodeTerritory(fromOrd),
                decodeTerritory(toOrd));
    }

    public static int encodeSide(Side side) {
        return (side == Side.DARK ? 0 : 1);
    }

    public static Side decodeSide(int iSide) {
        if (iSide == 0) {
            return Side.DARK;
        }
        if (iSide == 1) {
            return Side.LIGHT;
        }
        throw new IllegalArgumentException(String.valueOf(iSide));
    }

    public static int encodeShelobRule(ShelobRule rule) {
        return rule.ordinal();
    }

    public static ShelobRule decodeShelobRule(int iRule) {
        return ShelobRule.values()[iRule];
    }

    public static int encodeCard(ECard ecard) {
        return ecard.ordinal();
    }

    public static ECard decodeCard(int iec) {
        return ECard.values()[iec];
    }

    public static int encodeBoolean(boolean b) {
        return (b ? 1 : 0);
    }

    public static boolean decodeBoolean(int ib) {
        if (ib != 0 && ib != 1) {
            throw new IllegalArgumentException(ib + "");
        }
        return (ib == 0 ? false : true);
    }

    public static String encodePlacement(Map<EActor, ETerritory> placement) {
        if (placement.keySet().size() != 9) {
            throw new IllegalArgumentException("Incomplete placement.");
        }
        StringBuilder sb = new StringBuilder();
        for (EActor ea : placement.keySet()) {
            int iea = encodeActor(ea);
            int iet = encodeTerritory(placement.get(ea));
            sb.append(String.format("%02x%02x", iea, iet));
        }

        return sb.toString();
    }

    public static Map<EActor, ETerritory> decodePlacement(String s) {
        if (s.length() != 36) {
            throw new IllegalArgumentException("String is not of the correct length (36).");
        }
        Map<EActor, ETerritory> map = new HashMap<EActor, ETerritory>();

        for (int i = 0; i < 36; i+=4) {
            int iea = Integer.parseInt(s.substring(i, i+2),16);
            int iet =Integer.parseInt(s.substring(i+2, i+4),16);
            map.put(decodeActor(iea), decodeTerritory(iet));
        }


        return map;

    }

//    static void testMove() {
//        final int LOOPS = 1000;
//        for (int i = 0; i < LOOPS; i++) {
//            EActor atk = EActor.values()[(int) (Math.random() * EActor.values().length)];
//            EActor def = EActor.values()[(int) (Math.random() * EActor.values().length)];
//            ETerritory from = ETerritory.values()[(int) (Math.random() * ETerritory.values().length)];
//            ETerritory to = ETerritory.values()[(int) (Math.random() * ETerritory.values().length)];
//
//            Move p = new Move(atk, def, from, to);
//            int iMove = Codec.encodeMove(p);
//            Move q = Codec.decodeMove(iMove);
//            if (!(p.attacker == q.attacker && p.defender == q.defender &&
//                    p.from == q.from && p.to == q.to)) {
//                System.out.println("ERROR! " + p + " -> " + q);
//            }
//        }
//    }

//    public static void main(String[] args) {
//        Map<EActor, ETerritory> map = new HashMap<EActor, ETerritory>();
//        map.put(BALROG, SHIRE);
//        map.put(CAVETROLL, SHIRE);
//        map.put(SARUMAN, SHIRE);
//        map.put(GANDALF, SHIRE);
//        map.put(BOROMIR, ARTHEDAIN);
//        map.put(GIMLI, CARDOLAN);
//        map.put(MERRY, RHUDAUR);
//        map.put(PIPPIN, EREGION);
//        map.put(ARAGORN, ENEDWAITH);
//
//        System.out.println(map);
//        String encMap = encodePlacement(map);
//        System.out.println(encMap);
//        Map<EActor, ETerritory> decMap = decodePlacement(encMap);
//        System.out.println(decMap);
//        System.out.println(decMap.equals(map));
//
//
//    }
}
